<!DOCTYPE html>
<html lang="en">
	<head>
	  <meta charset="UTF-8">
	  <meta name="viewport" content="width=device-width, initial-scale=1.0">
	  <meta http-equiv="X-UA-Compatible" content="ie=edge">
	  <title>Document</title>
	</head>
	<body>	
		<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
		<script>
			// console.log(...[1,2,3]);//1 2 3
			// console.log(1,...[2,3,4],5);//1 2 3 4 5
			// console.log([...document.querySelectorAll('div')]);//[]

			// function push(array,...items){
			// 	array.push(...items);
			// }
			// function add(x,y){
			// 	return x+y;
			// }
			// const numbers = [4,38];
			// console.log(add(...numbers));//42


			// function f(v,w,x,y,z){ return v+w }
			// const args = [0,1];
			// console.log(f(-1,...args,2,...[3]));//-1

			// const arr = [
			// ...(x>0?['a']:[]),'b'];

			// console.log([...[],1]);//[1]

			// 扩展运算符如果放在括号中，JavaScript 引擎就会认为这是函数调用
			// (...[1, 2])//Uncaught SyntaxError: Invalid destructuring assignment target
			// console.log((...[1,2]));//Uncaught SyntaxError: Invalid destructuring assignment target

			// console.log(...[1, 2])//1 2


			// ES5 的写法
			// function f(x,y,z){
			// 	return x+y+z;
			// }
			// var args = [0,1,2];
			// var a = f.apply(null,args);
			// console.log(a);//3

			// ES6的写法
			// function f(x,y,z){
			// 	return x+y+z;
			// }
			// let args = [0,1,4];
			// console.log(f(...args));//5

			// ES5 的写法
			// Math.max.apply(null,[14,3,77])
			// ES6 的写法
			// Math.max(...[14,3,77]);
			//等同于
			// Math.max(14,3,77);

			// var arr1 = [0,1,2];
			// var arr2 = [3,4,5];
			// console.log(array.prototype.push.apply(arr1,arr2));

			// let arr1 = [0,1,2];
			// let arr2 = [3,4,5];
			// arr1.push(...arr2);
			// console.log(arr2);//[3, 4, 5]

			// console.log(new (Date.bind.apply(Date,[null,2015,1,1])));//Sun Feb 01 2015 00:00:00 GMT+0800 (中国标准时间)

			// console.log(new Date(...[2015,1,1]));//Sun Feb 01 2015 00:00:00 GMT+0800 (中国标准时间)

			// const a1 = [1,2];
			// const a2 = a1;
			// a2[0] = 2;
			// console.log(a1);//[2, 2]

			// const a1 = [1,2];
			// const a2 = a1.concat();
			// a2[0] = 2;
			// console.log(a1);//[1, 2]

			// const a1 = [1,2];
			// 写法一
			// const a2 = [...a1];
			// 写法二
			// const [...a2] = a1;
			// console.log(a1);//[1, 2]

			// const arr1 = ['a','b'];
			// const arr2 = ['c'];
			// const arr3 = ['d','e'];
			// console.log(arr1.concat(arr2,arr3));//["a", "b", "c", "d", "e"]
			// console.log([...arr1,...arr2,...arr3]);//["a", "b", "c", "d", "e"]

			// const a1 = [{foo:1}];
			// const a2 = [{bar:2}];
			// const a3 = a1.concat(a2);
			// const a4 = [...a1,...a2];
			// console.log(a3[0] === a1[0]);// true
			// console.log(a4[0] === a1[0]);// true

			// ES5
			// a = list[0],
			// rest = list.slice(1);
			
			// ES6
			// [a, ...rest] = list;

			// const [first,...rest] = [1,2,3,4,5];
			// console.log(first);//1
			// console.log(rest);//[2, 3, 4, 5]

			// const [first,...rest] = [];
			// console.log(first);//undefined
			// console.log(rest);//[]

			// const [first,...rest] = ['foo'];
			// console.log(first);//foo
			// console.log(rest);//[]

			//将扩展运算符用于数组赋值，只能放在参数的最后一位，否则会报错
			// const [...butLast,last] = [1,2,3,4,5];//Uncaught SyntaxError: Rest element must be last element
			// const [first,...middle,last] = [1,2,3,4,5];//Uncaught SyntaxError: Rest element must be last element

			// 扩展运算符还可以将字符串转为真正的数组
			// console.log([...'hello']);//["h", "e", "l", "l", "o"]

			// console.log('x\uD83D\uDE80y'.length);//4
			// console.log([...'x\uD83D\uDE80y'].length);//3

			// function length(str){
			// 	return [...str].length;
			// }
			// console.log(length('x\uD83D\uDE80y'));//3

			// let str = 'x\uD83D\uDE80y';
			// console.log(str.split('').reverse().join(''));//y��x
			// console.log([...str].reverse().join(''));//y🚀x


			// querySelectorAll方法返回的是一个NodeList对象。它不是数组，而是一个类似数组的对象。这时，扩展运算符可以将其转为真正的数组，原因就在于NodeList对象实现了 Iterator
			// let nodeList = document.querySelectorAll('div');
			// let array = [...nodeList];

			// Number.prototype[Symbol.iterator] = function *(){
			// 	let i = 0;
			// 	let num = this.valueOf();
			// 	while(i<num){
			// 		yield i++;
			// 	}
			// }
			// console.log([...5]);//[0, 1, 2, 3, 4]


			// arrayLike是一个类似数组的对象，但是没有部署 Iterator 接口，扩展运算符就会报错。这时，可以改为使用Array.from方法将arrayLike转为真正的数组
			// let arrayLike = {
			// 	'0':'a',
			// 	'1':'b',
			// 	'2':'c',
			// 	length:3
			// }
			// let arr = [...arrayLike];//Uncaught TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))

			// const go = function*(){
			// 	yield 1;
			// 	yield 2;
			// 	yield 3;
			// };
			// console.log([...go()]);//[1, 2, 3]

			//如果对没有 Iterator 接口的对象，使用扩展运算符，将会报错
			// const obj = {a: 1, b: 2};
			// let arr = [...obj];//Uncaught TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))

			// let ps = document.querySelectorAll('p');
			// Array.from(ps).filter(p =>{
			// 	retrun p.textContent.length>100;
			// });

			// function foo(){
			// 	var args = Array.from(arguments);
			// }

			// console.log(Array.from('hello'));//["h", "e", "l", "l", "o"]

			// let nameSet = new Set(['a','b']);
			// console.log(Array.from(nameSet));//["a", "b"]

			// function foo(){
			// 	const args = [...arguments];
			// }
			// [...document.querySelectorAll('div')];

			// console.log(Array.from({length:3}));//[undefined, undefined, undefined]

			// const toArray = (()=> Array.from?Array.from:obj =>[].slice.call(obj))();
			// console.log(toArray);//from() { [native code] }

			// console.log(Array.from(arrayLike, x => x * x));//Uncaught ReferenceError: arrayLike is not defined

			//console.log(Array.from(arrayLike).map(x => x * x));//Uncaught ReferenceError: arrayLike is not defined

			// console.log(Array.from([1,2,3],(x) =>x*x))//[1, 4, 9];

			// let spans = document.querySelectorAll('span.name');
			// let names1 = Array.property.map.call(spans,s => s.testContent);
			// let names = Array.from(spans,s => s.textContent);
			// let names2 = Array.from(spans,s => s.textContent);


			// console.log(Array.from([1,,2,,3],(n) => n || 0));//[1, 0, 2, 0, 3]

			// function typesOf () {
			//   return Array.from(arguments, value => typeof value)
			// }
			// console.log(typesOf(null,[],NaN));//["object", "object", "number"]

			// console.log(Array.from({ length: 2 }, () => 'jack'))// ["jack", "jack"]


			// 将字符串转为数组，然后返回字符串的长度。因为它能正确处理各种 Unicode 字符，可以避免 JavaScript 将大于\uFFFF的 Unicode 字符，算作两个字符的 bug
			// function countSymbols(string){
			// 	return Array.from(string).length;
			// }
			// console.log(countSymbols("\uFFFF"));//1

			//console.log(Array.of(3,11,8));//[3, 11, 8]
			// console.log(Array.of(3));//[3]
			// console.log(Array.of(3).length);//1

			// console.log(Array());//[]
			// console.log(Array(3));//[empty × 3]
			// console.log(Array(2,3,4))//[2, 3, 4]

			// console.log(Array.of());//[]
			// console.log(Array.of(undefined));//[undefined]
			// console.log(Array.of(1));//[1]
			// console.log(Array.of(1,2));//[1, 2]

			// function ArrayOf(){
			// 	return [].slice.call(arguments);
			// }

			// Array.prototype.copyWithin(1,start = 0,end = this.length);

			// console.log([1,2,3,4,5].copyWithin(0,3));//将从 3 号位直到数组结束的成员（4 和 5），复制到从 0 号位开始的位置，结果覆盖了原来的 1 和 2

			// console.log([1,2,3,4,5].copyWithin(0,3,4));//[4, 2, 3, 4, 5]

			// console.log([1,2,3,4,5].copyWithin(0,-2,-1));//[4, 2, 3, 4, 5]

			// console.log([].copyWithin.call({length:5,3:1},0,3));//{0: 1, 3: 1, length: 5}
			//({0:undefined,1:undefined,2:undefined,3: 1,4:undefined,5:undefined,length: 5}).copyWithin(0,3,5);
			// 结果为：
			// {0:1,1:undefined,2:undefined,3: 1,4:undefined,5:undefined,length: 5};
			// 首先去了解copyWithin()方法的基本使用。
			// 对象{length: 5, 3: 1}有两个属性。
			// length属性决定此对象为类数组对象，因此可使用copyWithin方法；
			// 另外有一个key为3值为1的属性。
			// 将3号位复制到0号位，因此导致创建key为0，值为1（与key为3的值一样）的属性。
			// 返回{0: 1, 3: 1, length: 5}



			// let i32a = new Int32Array([1,2,3,4,5]);
			// console.log(i32a.copyWithin(0,2));//[3, 4, 5, 4, 5]


			// console.log([].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4));//Int32Array(5) [4, 2, 3, 4, 5]

			// console.log([1, 4, -5, 10].find((n) => n < 0));//-5

			// console.log([1,5,10,15].find(function(value,index,arr){
			// 	return value>9;
			// }))//10

			// console.log([1,5,10,15].findIndex(function(value,index,arr){
			// 	return value>9;
			// }))//2

			//find函数接收了第二个参数person对象，回调函数中的this对象指向person对象
			// function f(v){
			// 	return v>this.age;
			// }
			// let person = {name:'John',age:20};
			// console.log([10,12,26,15].find(f,person));//26


			// console.log([NaN].indexOf(NaN));//-1

			// console.log([NaN].findIndex(y => Object.is(NaN, y)));//0

			// console.log(['a','b','c'].fill(7))//[7, 7, 7]

			// console.log(new Array(3).fill(7));// [7, 7, 7]

			// console.log(['a', 'b', 'c'].fill(7,1,2))//["a", 7, "c"]

			// let arr = new Array(3).fill({name:'Mike'});
			// arr[0].name = 'Ben';
			// console.log(arr);//// [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}]

			// let arr = new Array(3).fill([]);
			// arr[0].push(5);
			// console.log(arr);
			// [[5], [5], [5]]

			// for (let index of ['a', 'b'].keys()) {
			//   console.log(index);
			// }// 0 // 1

			// for(let elem of ['a','b'].values()){
			// 	console.log(elem);
			// }
			// 'a' // 'b'

			//keys()是对键名的遍历、values()是对键值的遍历，entries()是对键值对的遍历
			// for(let [index,elem] of ['a','b'].entries()){
			// 	console.log(index,elem);
			// }// 0 "a" // 1 "b"

			// let letter = ['a','b','c'];
			// let entries = letter.entries();
			// console.log(entries.next().value);// [0, 'a']
			// console.log(entries.next().value);// [1, 'b']
			// console.log(entries.next().value);// [2, 'c']
			// console.log(entries.next().value);
			// undefined

			// console.log([1,2,3].includes(2));//true
			// console.log([1,2,3].includes(4));//false
			// console.log([1,2,NaN].includes(NaN));//true

			// console.log([1,2,3].includes(3,3));//false
			// console.log([1,2,3].includes(3,-1));//true

			// const contains = (() =>
			// 	Array.prototype.includes
			// 	?(arr,value) => arr.includes(value)
			// 	:(arr,value) => arr.some(el =>el ===value)
			// )();
			// console.log(contains(['foo','bar'],'baz'));//false


			// console.log([1,2,[3,4]].flat());//[1, 2, 3, 4]
			// console.log([1, 2, [3, [4, 5]]].flat());// [1, 2, 3, [4, 5]]
			// console.log([1, 2, [3, [4, 5]]].flat(2));// [1, 2, 3, 4, 5]

			// console.log([1,[2,[3,4]]].flat(Infinity))//[1, 2, 3, 4]

			// console.log([1, 2, , 4, 5].flat());//[1, 2, 4, 5]

			// 相当于 [[2, 4], [3, 6], [4, 8]].flat()
			// console.log([2,3,4].flatMap((x) =>[x,x * 2]));//[2, 4, 3, 6, 4, 8]

			// 相当于 [[[2]], [[4]], [[6]], [[8]]].flat()
			// console.log([1, 2, 3, 4].flatMap(x => [[x * 2]]))
			// [[2], [4], [6], [8]]

			// console.log(0 in [undefined, undefined, undefined]);//true
			// console.log(0 in [, , ,]);//false


			// [,'a'].forEach((x,i) => console.log(i));//1

			// console.log(['a',,'b'].filter(x => true));// ['a','b']


			// console.log([,'a'].every(x => x==='a'));//true

			// console.log([1,,2].reduce((x,y) => x+y));//3

			// console.log([,'a'].some(x => x !== 'a'));//false

			// console.log([,'a'].map(x => 1));//[,1]

			// console.log([,'a',undefined,null].join('#'));// "#a##"

			// console.log([,'a',undefined,null].toString())//,a,,

			//Array.from方法会将数组的空位，转为undefined
			// console.log(Array.from(['a',,'b']));
			// [ "a", undefined, "b" ]
			//扩展运算符（...）也会将空位转为undefined
			// console.log([...['a',,'b']]);
			// [ "a", undefined, "b" ]

			// console.log([,'a','b',,].copyWithin(2,0))// [,"a",,"a"]

			// console.log(new Array(3).fill('a'));// ["a","a","a"]

			// let arr = [,,];
			// for(let i of arr){
			// 	console.log(1);
			// }// 1 // 1

			// console.log([...[,'a'].entries()]);// [[0,undefined], [1,"a"]]

			// console.log([...[,'a'].keys()]);// [0,1]
			// console.log([...[,'a'].values()])// [undefined,"a"]
			// console.log([,'a'].find(x => true));//undefined
			// console.log([,'a'].findIndex(x => true));//0

			





		</script>	
	</body>
</html>